﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SIA.Configurators;

namespace SIA.HwAccess
{
    public delegate void MsgNotifier(string message, MessageType msgType);
    public enum MessageType
    {
        ERROR = 0,
        RUNTIME = 1,
        INFO = 2,
        DEBUG = 3
    }

    public abstract class HwResource : IHwResource
    {
        protected String _name = "";
        protected String _group = "";
        protected String _comment = "";
        protected IDictionaryProperty _dProperty = new SimpleDictionaryProperty("VOID", "VOID");

        public String Name { get { return _name; } }
        public String Group { get { return _group; } set { _group = value; } }
        public String Comment { get { return _comment; } set { _comment = value; } }
        public IDictionaryProperty DictionaryProperty { get { return _dProperty; } }
    }

    public abstract class HwDevice : HwResource, IHwDevice
    {
        protected IHwConnections _connections = new HwConnections();
        protected eDeviceStatus _status = eDeviceStatus.UNDEF;

        public IHwConnections Connections { get { return _connections;} }

        public eDeviceStatus Status { 
            get {
                foreach (IHwConnection c in _connections.Values)
                {
                    if (c.Status == eConnectionStatus.ERROR || c.Status == eConnectionStatus.UNDEF)
                        _status = eDeviceStatus.FAULT;
                    if (c.Status == eConnectionStatus.CONNECT)
                        _status = eDeviceStatus.OK;
                    
                    if (_status == eDeviceStatus.OK)
                        continue;
                    if (_status == eDeviceStatus.FAULT)
                        break;

                    _status = eDeviceStatus.UNDEF;
                }
                return _status; 
            } }
    }

    public abstract class HwConnection : HwResource, IHwConnection
    {
        protected IHwSignalsGroup _signalGroup = null;
        protected IHwSignals _signals = new HwSignals();
        protected eConnectionStatus _status = eConnectionStatus.UNDEF;
        protected IRawData _rawData = null;

        public IRawData RawData { get {
                return _rawData;
        } }
        public IHwSignalsGroup SignalsGroup { get { return _signalGroup; } }
        public IHwSignals Signals { get { return _signals; } }
        public abstract eConnectionStatus Status { get; }// { //return _status; } }

        abstract public void connect();        
        abstract public void disconnect();
        abstract public void register(IHwSignal signal);

        abstract public event ConnectionStatus StatusChange;
        abstract public event ConnectionDataEvent DataArrived;

        public virtual void requestWriteData(IHwAddress address, int offset, Byte value)
        {
                if (!this._rawData.ContainsKey(address.DataKey))
                    this._rawData.Add(address.DataKey, new Byte[4096]);

                if (this._rawData[address.DataKey].Length <= (address.StartByte + offset))
                        this._rawData[address.DataKey] = new Byte[4096];

                this._rawData[address.DataKey][address.StartByte + offset] = value;
            }
        }

    public abstract class HwSignalsGroup: HwResource, IHwSignalsGroup
    {
        protected IHwSignals _signals = new HwSignals();
        public IHwSignals Signals { get { return _signals; } }

        public void Merge(IHwSignals signals)
        {
            foreach (IHwSignal s in signals.Values)
                if (!_signals.ContainsKey(s.Name)) _signals.Add(s.Name, s);
        }

        public IHwSignal this[string key]
        {
            get { return _signals[key]; }
        }

        public void Add(IHwSignal signal)
        {
            if (!_signals.ContainsKey(signal.Name))
                _signals.Add(signal.Name, signal);
        }
    }

    public abstract class HwSignal : HwResource, IHwSignal
    {
        public abstract Object Value { get; set; }

        protected IHwConnection _connection = null;
        protected eReadWrite _readWrite = eReadWrite.NONE;

        public IHwConnection Connection { get { return _connection; } set { _connection = value; } }
        public eReadWrite ReadWrite { get { return _readWrite; }  }
        
        public abstract event SignalEvent ValueChange;

    }
}
